<template>
  <div
    id="container"
    name="container"
    class="parent page-wrapper p-20 d-flex flex-column div-main"
  >
    <!-- <div class="main-header">信访大厅视频安防系统</div> -->

    <div id="info" class="info" @click="onLabelClick">
      <div class="info-title">人员信息</div>
      <div class="info-pic">
        <img src="/img/avatar3.jpeg" />
        <div class="info-div">
          <div>姓名: 张晓婷</div>
          <div>类型: 非法闯入</div>
        </div>
      </div>
    </div>
    <!-- <div class="level">
      <el-timeline>
        <el-timeline-item
          v-for="(activity, index) in activities"
          :key="index"
          :color="activity.color"
        >
          <div
            class="custom-timeline-item"
            @click="handleTimelineItemClick(activity)"
          >
            <p :class="[activity.isActive ? 'level-active' : 'level-normal']">
              {{ activity.content }}
            </p>
          </div>
        </el-timeline-item>
      </el-timeline>
    </div> -->
    <!--  内容-->
    <!-- <div id="can" class="heatMap" style="display: none"></div> -->
    <!-- <div class="div-content">
      <div class="div-left">
        <div class="left-top">
          <left-top></left-top>
        </div>
        <div class="left-middle">
          <left-middle></left-middle>
        </div>
        <div class="left-bottom">
          <left-bottom></left-bottom>
        </div>
      </div>
    </div> -->
    <div class="div-right">
      <MyButton class="mr-20" icon="el-icon-plus" @click="handleAdd"
        >显示轨迹</MyButton
      >
    </div>
  </div>
</template>

<script>
import LeftTop from "./LeftTop";
import LeftMiddle from "./LeftMiddle";
import LeftBottom from "./LeftBottom";
import util from "@/utils";
import * as THREE from "three";
import h337 from "heatmap.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import * as dat from "dat.gui";
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer";
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass";
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass";
import { OutputPass } from "three/examples/jsm/postprocessing/OutputPass";
import {
  CSS3DRenderer,
  CSS3DObject,
  CSS3DSprite,
} from "three/examples/jsm/renderers/CSS3DRenderer";
import {
  CSS2DRenderer,
  CSS2DObject,
} from "three/examples/jsm/renderers/CSS2DRenderer.js";
import { getPath } from "./api/service";
import LabelManager from "./api/label.manager";

export default {
  components: {
    LeftTop,
    LeftMiddle,
    LeftBottom,
  },
  data() {
    return {
      show: true,
      scene: null,
      texture: null,
      progress: 0.0,
      current: -1,
      gltfModel: null,
      mark: null,
      building: null,
      lastTime: 0,
      clock: new THREE.Clock(),
      speed: 0.2,
      scale: 0.11,
      circleMesh: null,
      ringMesh: null,
      texture: null,
      lastTimeHeatMap: 0,
      firstCamera: false,
      progress: 0,
      showTrace: false,
    };
  },
  mounted() {
    this.init();
    this.loadModel("xf-prod.glb");
    // this.createHeat();
    // this.addMark();
    this.animate();
  },
  methods: {
    init() {
      this.scene = new THREE.Scene();

      //初始化渲染器
      let container = document.getElementById("container");
      let height = container.offsetHeight;
      let width = container.offsetWidth;

      // 初始化相机
      this.camera = new THREE.PerspectiveCamera(
        50,
        width / height,
        0.01,
        10000
      );

      this.camera.position.set(47, 15, 29);
      this.camera.rotation.set(-Math.PI / 7, Math.PI / 4, Math.PI / 10);
      this.camera.lookAt(0, 0, 0);
      this.scene.add(this.camera);

      let hLight = new THREE.AmbientLight(0xffffff, 5);
      this.scene.add(hLight);

      //  添加 CSS3DRenderer
      this.cssRender = new CSS3DRenderer();
      this.cssRender.setSize(width, height);
      this.cssRender.domElement.style.position = "absolute";
      this.cssRender.domElement.style.top = "0px";
      container.appendChild(this.cssRender.domElement);

      // 创建 LabelManager 实例

      this.labelManager = new LabelManager(this.scene);
      const label = this.labelManager.createLabel(
        "人员闯入1",
        new THREE.Vector3(1, 2.5, 1),
        this.onLabelClick
      );
      //label.userData.target = this.cube; // 关联标签和目标立方体
      this.scene.add(label);

    
      this.renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true,
        logarithmicDepthBuffer: true,
      });
      this.renderer.setSize(width, height);
      container.appendChild(this.renderer.domElement);

      //初始化控制器
      this.controls = new OrbitControls(this.camera, this.cssRender.domElement);

      this.controls.minDistance = 10;
      this.controls.maxDistance = 500;
      // // 上下旋转范围
      this.controls.minPolarAngle = 0; // radians
      this.controls.maxPolarAngle = Math.PI * 0.5; // radians
      // // 左右旋转范围

      window.addEventListener("resize", this.onWindowResize, false);

      // const renderScene = new RenderPass(this.scene, this.camera);

      // const bloomPass = new UnrealBloomPass(
      //   new THREE.Vector2(window.innerWidth, window.innerHeight),
      //   1.5,
      //   0.4,
      //   0.85
      // );

      // const params = {
      //   threshold: 0,
      //   strength: 0.2,
      //   radius: 0,
      //   exposure: 0.5,
      // };
      // bloomPass.threshold = params.threshold;
      // bloomPass.strength = params.strength;
      // bloomPass.radius = params.radius;

      // const outputPass = new OutputPass();

      // this.composer = new EffectComposer(this.renderer);
      // this.composer.addPass(renderScene);
      // this.composer.addPass(bloomPass);
      // this.composer.addPass(outputPass);

      // const gui = new dat.GUI();

      // const bloomFolder = gui.addFolder("bloom");

      // bloomFolder.add(params, "threshold", 0.0, 1.0).onChange(function (value) {
      //   bloomPass.threshold = Number(value);
      // });

      // bloomFolder.add(params, "strength", 0.0, 3.0).onChange(function (value) {
      //   bloomPass.strength = Number(value);
      // });

      // gui
      //   .add(params, "radius", 0.0, 1.0)
      //   .step(0.01)
      //   .onChange(function (value) {
      //     bloomPass.radius = Number(value);
      //   });

      // const toneMappingFolder = gui.addFolder("tone mapping");

      // toneMappingFolder
      //   .add(params, "exposure", 0.1, 2)
      //   .onChange(function (value) {
      //     renderer.toneMappingExposure = Math.pow(value, 4.0);
      //   });
    },
    onWindowResize() {
      let container = document.getElementById("container");
      let height = container.offsetHeight;
      let width = container.offsetWidth;

      this.camera.aspect = width / height;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(width, height);
    },

    generateHeatmapData() {
      for (let y = 0; y < 10; y++) {
        for (let x = 0; x < 10; x++) {
          const value = Math.floor(Math.random() * 3); // 生成 0 到 3 的随机值
          const idx = (x + y * 10) * 3;

          // 根据 value 的强度设置颜色
          this.heatmapData[idx] = value * 60; // R
          this.heatmapData[idx + 1] = 0; // G
          this.heatmapData[idx + 2] = value * 60; // B
        }
      }
    },

    createHeat() {
      this.heatmap = h337.create({
        container: document.getElementById("can"),
        width: 512, //这里一定要2的n次方倍数,否则控制台报警告（定死，与后面坐标系计算强关联）
        height: 512, //这里一定要2的n次方倍数,否则控制台报警告（定死，与后面坐标系计算强关联）
        maxOpacity: 0.6,
        radius: 50,
        blur: 1,
        gradient: {
          0.1: "blue",
          0.3: "green",
          0.5: "yellow",
          0.7: "orange",
          1.0: "red",
        },
      });

      var points = this.genData();
      var data = {
        max: 100,
        data: points,
      };

      this.heatmap.setData(data);

      this.texture = new THREE.CanvasTexture(this.heatmap._renderer.canvas);

      this.texture.needsUpdate = true;
      //  const texture = new THREE.Texture(heatmap._renderer.canvas);
      var material = new THREE.MeshLambertMaterial({
        map: this.texture,
        transparent: true,
        opacity: 1,
        side: THREE.DoubleSide,
      });

      var mesh = new THREE.Mesh(new THREE.PlaneGeometry(15, 15), material);
      mesh.rotation.x = Math.PI / 2;
      mesh.position.set(13, 1.5, 6);
      this.scene.add(mesh);
    },

    genData() {
      var points = [];
      var max = 0;
      var width = 200;
      var height = 200;
      var len = 10;

      while (len--) {
        var val = Math.floor(Math.random() * 100);
        //  max = Math.max(max, val);
        var point = {
          x: Math.floor(Math.random() * width),
          y: Math.floor(Math.random() * height),
          value: val,
        };
        points.push(point);
      }
      return points;
    },
    loadModel(modelName) {
      let that = this;
      const loader = new GLTFLoader();
      loader.setPath("/model/");

      var mats = new THREE.MeshBasicMaterial({
        color: 0xababab,
        transparent: false,
        opacity: 0.9,
      });
      var matGlow = new THREE.MeshStandardMaterial({
        color: 0xffffff,
        metalness: 1,
        roughness: 0,
        transparent: true,
        opacity: 0.6,
      });
      loader.load(modelName, (gltf) => {
        if (modelName == "mark.glb") {
          this.mark = gltf.scene;
          // 对模型进行放大
          this.mark.scale.set(20, 20, 20); // 按照需要的倍数进行放大
          this.mark.rotation.y = 0;
          this.mark.position.set(0, 0, 0);
          this.scene.add(this.mark);
        } else {
          gltf.scene.traverse(function (child) {
            if (child.isMesh) {
              if (
                child.name.includes("wall") ||
                child.name.includes("stair") ||
                child.name.includes("screen") ||
                child.name.includes("desk") ||
                child.name.includes("pillar") ||
                child.name.includes("slope") ||
                child.name.includes("chair")
              ) {
                console.log(child.name);
                // child.material = matGlow;

                const edges = new THREE.EdgesGeometry(child.geometry);
                const lineMaterial = new THREE.LineBasicMaterial({
                  color: 0xfffffff,
                  linewidth: 1,
                });
                const edgesMesh = new THREE.LineSegments(edges, lineMaterial);
                that.scene.add(edgesMesh);
              }
            }
          });
          this.building = gltf.scene;
          // 对模型进行放大
          this.scene.add(this.building);
          this.createTag();
        }
      });
    },

    addMark() {
      var geo = new THREE.BoxGeometry(0.5, 0.5, 0.5);
      var mat = new THREE.MeshStandardMaterial({
        color: "#00ab00",
        side: THREE.DoubleSide,
        emissiveIntensity: 10,
      });
      var mark = new THREE.Mesh(geo, mat);
      mark.position.set(0, 2, 0);

      this.scene.add(mark);

      const gui = new dat.GUI();
      gui.add(mark.position, "x", -30, 90, 0.01);
      gui.add(mark.position, "y", 0, 20, 0.01);
      gui.add(mark.position, "z", -50, 30, 0.01);
    },

    animate() {
      requestAnimationFrame(this.animate);

      const elapsedTime = this.clock.getElapsedTime();

      // 刷新地图时间
      if (elapsedTime - this.lastTime >= 0.05) {
        //刷新势力图时间
        if (elapsedTime - this.lastTimeHeatMap > 2) {
          var points = this.genData();
          var data = {
            max: 100,
            data: points,
          };

          // this.heatmap.setData(data);
          // this.texture.needsUpdate = true;
          this.lastTimeHeatMap = elapsedTime;
        }
        if (this.showTrace) {
          // console.log(this.progress);
          if (this.progress < 1) {
            this.progress += 0.003;
            let point = this.curve.getPointAt(this.progress);
            let nextPoint = this.curve.getPointAt(this.progress + 0.0002);
            let prePoint = this.curve.getPointAt(this.progress - 0.0002);
            if (point && point.x) {
              if (this.ringMesh != null) {
                if (!this.firstCamera) {
                  if (this.ringMesh) {
                    this.circleMesh.position.set(point.x, point.y, point.z);
                    this.ringMesh.position.set(point.x, point.y, point.z);
                    if (this.ringMesh.scale.x > 1.5) {
                      this.ringMesh.scale.x = 1;
                      this.ringMesh.scale.y = 1;
                    }
                    this.ringMesh.scale.x += this.scale;
                    this.ringMesh.scale.y += this.scale;
                  }
                }
                if (this.firstCamera) {
                  this.camera.position.set(point.x, 10, point.z);
                  this.camera.lookAt(nextPoint.x, 0, nextPoint.z);
                }
                // console.log(this.progress);
              }
            }
          }
        }

        this.renderer.render(this.scene, this.camera);
        this.cssRender.render(this.scene, this.camera);
        //  console.log(this.labelRenderer);
        // this.labelRenderer.render(this.scene, this.camera);
        // this.composer.render();
        if (!this.showTrace) {
          this.trace();
        }

        // 更新 lastTime
        this.lastTime = elapsedTime;
      }
    },

    trace() {
      if (this.ringMesh) {
        if (this.ringMesh.position.x > 15 || this.ringMesh.position.x < 5) {
          this.speed = -this.speed;
        }
        this.circleMesh.position.x += this.speed;
        this.ringMesh.position.x += this.speed;
        if (this.ringMesh.scale.x > 1.5) {
          this.ringMesh.scale.x = 1;
          this.ringMesh.scale.y = 1;
        }
        this.ringMesh.scale.x += this.scale;
        this.ringMesh.scale.y += this.scale;
      }
    },
    createTag() {
      // 创建圆形几何体
      const radius = 0.3; // 圆的半径
      const segments = 32; // 圆的细分段数
      const circleGeometry = new THREE.CircleGeometry(radius, segments);

      // 创建材质
      const material = new THREE.MeshBasicMaterial({
        color: 0xff0000,
        side: THREE.DoubleSide,
      }); // 颜色为黄色，双面材质

      // 创建圆形网格
      this.circleMesh = new THREE.Mesh(circleGeometry, material);
      this.circleMesh.rotation.x = Math.PI / 2;
      this.circleMesh.position.set(5, 1.3, 10);
      this.scene.add(this.circleMesh);

      // 创建环形几何体
      const innerRadius = 0.4; // 内半径
      const outerRadius = 0.5; // 外半径
      const ringGeometry = new THREE.RingGeometry(
        innerRadius,
        outerRadius,
        segments
      );

      // 创建环形网格
      this.ringMesh = new THREE.Mesh(ringGeometry, material);
      this.ringMesh.rotation.x = Math.PI / 2;
      this.ringMesh.position.set(5, 1.3, 10);
      this.scene.add(this.ringMesh);
    },
    showAlarm() {
      let element = document.getElementById("info");
      // element.setAttribute("class", "hide-alarm");
      this.tag1 = new CSS3DSprite(element);
      this.tag1.position.x = -10;
      this.tag1.position.y = 0;
      this.tag1.position.z = 0;
      this.tag1.scale.set(0.025, 0.025, 0.025);
      this.cssScene.add(this.tag1);

      // var points = [];
      // points.push(new THREE.Vector3(0, 0, 0));
      // points.push(new THREE.Vector3(20, 10, 0));

      // var geometry = new THREE.BufferGeometry().setFromPoints(points);
      // var material = new THREE.LineBasicMaterial({ color: 0x00afed });

      // // 创建线对象并添加到场景
      // var line = new THREE.Line(geometry, material);
      // this.scene.add(line);
    },
    addClass(index, event) {
      this.current = index;
      console.log(index);
    },
    handleTimelineItemClick(item) {
      for (let i = 0; i < this.activities.length; i++) {
        this.activities[i].color = "#ffffff";
        this.activities[i].isActive = false;
      }
      item.isActive = true;
      item.color = "#35fff4";
    },
    onLabelClick() {
      alert("label click");
    },
    handleAdd() {
      this.labelManager.showLabel();
      const res = getPath({ mapId: "mapId" })
        .then((res) => {
          //轨迹
          var points = [];
          var jsonArray = res.data;
          // 使用 for 循环
          for (let i = 0; i < jsonArray.length; i++) {
            points.push(
              new THREE.Vector3(
                jsonArray[i].positionX,
                jsonArray[i].positionY,
                jsonArray[i].positionZ
              )
            );
          }

          // points.push(new THREE.Vector3(10, 0.2, 12));
          // points.push(new THREE.Vector3(10, 0.2, -15));
          // points.push(new THREE.Vector3(20, 0.2, -15));
          this.curve = new THREE.CatmullRomCurve3(
            points,
            false,
            "catmullrom",
            0.1
          );

          let tubeGeometry = new THREE.TubeGeometry(
            this.curve,
            100,
            0.1,
            50,
            false
          );
          let tubeMaterial = new THREE.MeshBasicMaterial({
            color: 0xff0000,
            wireframe: false,
          });
          this.tube = new THREE.Mesh(tubeGeometry, tubeMaterial);
          this.tube.visible = false;
          this.scene.add(this.tube);
          this.showTrace = true;
          this.progress = 0;
          console.log(res.data);
        })
        .catch((error) => {
          console.error(error);
        });
    },
  },
};
</script>

<style lang="less">
.parent {
  position: relative;
  font-size: 14px;
  height: 100%;
  //   background: #ababab;
  background: url("/img/t_bg.png") no-repeat center;
  border-radius: 20px;
  background-size: 100% 100%;
  width: 100%;
}
.main-header {
  width: 100%;
  height: 100px;
  position: absolute;
  top: 0px;
  background: url("/img/title_bg.png") no-repeat center;
  background-size: 100% 100%;
  color: #aabbdd;
  text-align: center;
  font-size: 47px;
  line-height: 60px;
  letter-spacing: 10px;
  font-weight: bolder;
}
.info {
  height: 150px;
  width: 300px;
  background: url("/img/panel.png") no-repeat center;
  background-size: 100% 100%;
  position: absolute;
  z-index: 5;
  pointer-events: auto; /* 确保允许鼠标事件 */
  cursor: pointer; /* 提示可点击 */
}
.hide-alarm {
  display: none;
}
.info-title {
  font-size: 16px;
  height: 55px;
  line-height: 60px;
  color: aliceblue;
  text-align: center;
}
.info-pic {
  padding: 10px 50px 10px 50px;
  color: aliceblue;
  display: flex;
}
.info-pic img {
  height: 60px;
  width: 60px;
}
.info-div {
  font-size: 13px;
  width: 130px;
  height: 60px;
  display: block;
  padding: 20px 0px 0px 30px;
}
.info-div div {
  height: 50%;
  line-height: 50%;
}

.info-detail {
  padding: 5px 50px 2px 50px;
  font-size: 13px;
  height: 30px;
  line-height: 23px;
  text-align: left;
  color: #02fe90;
}

.info-detail span {
  color: #02fe90;
  margin-left: 1.5rem;
}
.info-title:after {
  position: absolute;
  content: "";
  width: 80%;
  height: 1px;
  background: -webkit-linear-gradient(
    left,
    rgba(0, 216, 247, 0),
    #00afed,
    rgba(0, 216, 246, 0)
  );
  left: 50%;
  transform: translateX(-50%);
  top: 55px;
}

#menu {
  display: flex;
  cursor: pointer;
  transition: all 0.5s;
}
#menu li {
  font-size: 13px;
  width: 100px;
  height: 30px;
  line-height: 30px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  box-sizing: border-box;
  border-radius: 3px;
  text-align: center;
  justify-content: center;
  background-color: rgba(255, 255, 255, 0.3);
  margin-right: 2px;
}

#menu li:hover {
  background-color: rgba(255, 255, 255, 0.5) !important;
}

#menu li:active {
  background-color: #1abc9c !important;
  color: black;
}
.blue {
  background-color: #1abc9c !important;
  color: white;
}

.level {
  position: absolute;
  right: 50px;
  top: 190px;
}
.level-active {
  color: #35fff4;
  font-weight: bold;
  height: 35px;
}
.level-normal {
  color: white;
  height: 35px;
}

.div-content {
  height: calc(100% - 280px);
  margin-top: 100px;
  display: flex;
  width: 20%;
  min-width: 300px;
  position: absolute;
  padding: 0px 20px;
  border-radius: 10px;
  background-color: rgba(72, 80, 93, 0.3);
}

.div-right {
  height: 30px;
  width: 100px;
  position: absolute;
  margin-top: 80px;
  margin-right: 50px;
  right: 50px;
  z-index: 5;
}

.div-left {
  height: 100%;
  width: 100%;
  min-width: 300px;
  display: block;
  padding-top: 10px;
}
.left-top {
  height: 20%;
}

.left-bottom {
  margin-top: 20px;
}

.heatMap {
  width: 600px;
  height: 400px;
  border: 1px solid;
  border-color: gray;
}
.sprite {
  height: 100px;
  width: 200px;
  padding: 20px;
  background-color: rgba(100, 10, 10, 0.1);
  background-size: 100% 100%;
}
</style>
